package com.zhou.org.controller;


import com.zhou.framework.aop.anotation.LogOption;
import com.zhou.framework.aop.enums.LogLevel;
import com.zhou.framework.dto.IntegersDto;
import com.zhou.framework.model.PageResult;
import com.zhou.framework.model.RS;
import com.zhou.framework.exception.VerifyException;
import com.zhou.framework.redis.util.RedisLock;
import com.zhou.framework.util.PageUtil;
import com.zhou.framework.util.SettingUtil;
import com.zhou.util.StringTool;
import com.zhou.org.common.EnumConstant;
import com.zhou.org.dao.Org;
import com.zhou.org.dao.OrgRelation;
import com.zhou.org.dto.*;
import com.zhou.org.model.OrgTree;
import com.zhou.org.service.OrgService;
import com.zhou.org.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author lang.zhou
 * @since 2022-08-23
 */
@Api(tags = "组织架构接口")
@Slf4j
@RestController
@RequestMapping("/sys/org")
public class OrgController {
    @Autowired
    private OrgService orgService;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisLock redisLock;

    @GetMapping("/departmentTree")
    @LogOption(LogLevel.QUERY)
    @ApiOperation("获取部门树")
    public RS getDepartmentTree(){
        List<OrgTree> treeData=orgService.getOrgTree(EnumConstant.ORG_TYPE_DEPART);
        return RS.data(treeData);
    }

    @ApiOperation("获取角色列表")
    @LogOption(LogLevel.QUERY)
    @GetMapping("/listRole")
    public RS roles(){
        List<Org> roleList =orgService.getRoles();
        return RS.data(roleList);
    }

    @ApiOperation("id获取组织结构对象")
    @LogOption(value = LogLevel.QUERY,response = true)
    @GetMapping("/get/{orgId}")
    public RS getOrgById(@PathVariable Integer orgId){
        OrgTree org = orgService.getOrgObject(orgId);
        return RS.data(org);
    }


    @ApiOperation("获得用户所有父节点")
    @LogOption(LogLevel.QUERY)
    @GetMapping("/listParent")
    public RS listParent(@RequestParam Integer orgId){
        List<OrgTree> parentTree = orgService.getParentOrgObject(orgId);
        return RS.data(parentTree);
    }

    @ApiOperation("查询组织结构下的对象")
    @LogOption(LogLevel.QUERY)
    @PostMapping("/listChild")
    public Object listChild(@RequestBody @Validated OrgQueryDto dto){
        PageUtil.offsetPage(dto);
        List<OrgTree> list = orgService.getPageList(dto);
        for (OrgTree org : list) {
            List<OrgTree> parentOrgObject = orgService.findLatestParentCache(org.getOrgId());
            /*List<String> b = new ArrayList<>();
            OrgUtil.readOrg(parentOrgObject, b);
            org.setParentName(StringTool.join(b,"、"));*/
            org.setChilds(parentOrgObject);
        }
        return PageUtil.result(dto,list);
    }

    @ApiOperation("保存部门")
    @LogOption(value = LogLevel.EDIT,response = true)
    @PostMapping("/saveDepartment")
    public RS saveDepartment(@RequestBody @Validated OrgDto dto){
        dto.setOrgType(EnumConstant.ORG_TYPE_DEPART);
        String key = StringTool.join(Arrays.asList("saveOrg", dto.getPid(), dto.getOrgName()),"-");
        AtomicReference<Integer> orgId = new AtomicReference<>(0);
        boolean r = redisLock.lockAndRun(key, 60L, () -> {
            OrgQueryDto qd = new OrgQueryDto();
            qd.setOrgId(dto.getPid());
            qd.setOrgTypes(Collections.singletonList(EnumConstant.ORG_TYPE_DEPART));
            List<OrgTree> list = orgService.getChildrenList(qd);
            boolean b = list.stream().anyMatch(o -> Objects.equals(dto.getOrgName(), o.getOrgName()) && !Objects.equals(dto.getOrgId(), o.getOrgId()));
            if (b) {
                throw new VerifyException("该部门下存在同名组织结构");
            }

            Org org = orgService.saveOrg(dto);
            orgId.set(org.getOrgId());
        });
        return r ? RS.data(orgId.get()) : RS.failed("请稍后重试");
    }

    @ApiOperation("修改角色")
    @LogOption(value = LogLevel.EDIT,response = true)
    @PostMapping("/saveRole")
    public RS saveRole(@RequestBody @Validated RoleDto dto){
        int adminOrgId = SettingUtil.getAdminOrgId();
        if(adminOrgId > 0 && Objects.equals(dto.getOrgId(),adminOrgId)){
            return RS.failed("管理员角色不允许操作");
        }
        String key = "saveRole-" + dto.getOrgName();
        AtomicReference<Integer> orgId = new AtomicReference<>(0);
        boolean r = redisLock.lockAndRun(key, 60L, () -> {
            List<Org> list = orgService.getRoles();
            boolean b = list.stream().anyMatch(o -> Objects.equals(dto.getOrgName(), o.getOrgName()) && !Objects.equals(dto.getOrgId(), o.getOrgId()));
            if (b) {
                throw new VerifyException("角色名称已存在");
            }
            Org org = new Org();
            BeanUtils.copyProperties(dto,org);
            orgService.saveRole(org);
            orgId.set(org.getOrgId());
        });
        return r ? RS.data(orgId.get()) : RS.failed("请稍后重试");
    }

    /*@RequestMapping("/dragOrg")
    public RS dragOrg(@RequestBody @Validated OrgDragDto dto){
        RS r = new RS();
        OrgQueryDto qd = new OrgQueryDto();
        qd.setOrgId(dto.getPid());
        qd.setOrgTypes(Collections.singletonList(EnumConstant.ORG_TYPE_DEPART));
        List<OrgTree> list = orgService.getChildrenList(qd);
        Org org = orgService.getById(dto.getId());
        if(org != null){
            for(OrgTree obj : list){
                if(Objects.equals(org.getOrgName(),obj.getOrgName()) && !Objects.equals(org.getOrgId(),obj.getOrgId())){
                    Assert.error("该部门下存在同名组织结构！");
                }
            }
            orgService.saveDragOrg(dto);
        }
        return r;
    }*/

    @ApiOperation("组织结构下添加用户")
    @LogOption(value = LogLevel.EDIT,response = true)
    @PostMapping("/saveUserOrg")
    public RS saveUserOrg(@RequestBody @Validated OrgUserDto dto){
        boolean b = redisLock.lockAndRun("saveUserOrg-" + dto.getOrgId(), 60L, () -> {
            OrgQueryDto qd = new OrgQueryDto();
            qd.setOrgId(dto.getOrgId());
            qd.setOrgTypes(Collections.singletonList(EnumConstant.ORG_TYPE_USER));
            //查询已有的下级用户并去重
            List<Integer> userIdList = dto.getUserIds();
            List<Integer> list = orgService.getChildrenList(qd).stream().map(OrgTree::getUserId).collect(Collectors.toList());
            userIdList.removeIf(list::contains);

            if(userIdList.size() > 0){
                List<OrgRelation> data = new ArrayList<>(userIdList.size());
                Map<Integer,Integer> userOrgMap = userService.getOrgIdList(userIdList);
                for (Integer integer : userIdList) {
                    Integer orgId = userOrgMap.get(integer);
                    if(orgId != null){
                        OrgRelation relation = new OrgRelation();
                        relation.setFromId(dto.getOrgId());
                        relation.setToId(orgId);
                        data.add(relation);
                    }
                }
                orgService.addOrgRelation(data);
            }
        });

        return b ? RS.success() : RS.failed("请稍后重试");
    }

    @DeleteMapping("/delete")
    @LogOption(value = LogLevel.DELETE,response = true)
    @ApiOperation("批量删除组织架构对象")
    public RS deleteOrg(@RequestBody @Validated IntegersDto dto){
        for(Integer id : dto.getIds()){
            OrgQueryDto qd = new OrgQueryDto();
            qd.setOrgId(id);
            qd.setOrgTypes(Arrays.asList(EnumConstant.ORG_TYPE_DEPART,EnumConstant.ORG_TYPE_USER));
            List<OrgTree> list = orgService.getChildrenList(qd);
            if(list.size() > 0){
                return RS.failed("要删除的部分部门下存在子部门或用户，请检查！");
            }
        }
        orgService.deleteOrg(dto.getIds());
        return RS.success();
    }

    @DeleteMapping("/deleteUserOrg")
    @LogOption(value = LogLevel.DELETE,response = true)
    @ApiOperation("批量移除组织架构下面的用户")
    public RS deleteUserOrg(@RequestBody @Validated OrgRelationDelDto dto){
        orgService.deleteOrgRelation(dto);
        return RS.success();
    }

    /**
     * 部门和角色树
     */
    @ApiOperation("查询部门和角色树")
    @LogOption(LogLevel.QUERY)
    @GetMapping("/orgDepartTree")
    public RS orgTree(){
        List<OrgTree> dep = orgService.getOrgTree(EnumConstant.ORG_TYPE_DEPART);
        OrgTree role = new OrgTree();
        role.setOrgName("系统角色");
        role.setOrgType(EnumConstant.ORG_TYPE_ROLE);
        role.setOrgId(-10);
        role.setCanClick(false);
        List<Org> roles = orgService.getRoles();
        List<OrgTree> rr = new ArrayList<>(roles.size());
        for (Org org : roles) {
            OrgTree t = new OrgTree();
           BeanUtils.copyProperties(org,t);
           rr.add(t);
        }
        role.setChilds(rr);
        dep.add(role);
        return RS.data(dep);
    }

    @ApiOperation("查询部门和角色树(带用户)")
    @LogOption(LogLevel.QUERY)
    @GetMapping("/fullTree")
    public RS fullTree(){
        List<OrgTree> dep = orgService.getMainTree();
        List<OrgTree> roles = new ArrayList<>();
        List<OrgTree> users = new ArrayList<>();
        for (Iterator<OrgTree> iterator = dep.iterator(); iterator.hasNext(); ) {
            OrgTree menuTree = iterator.next();
            if(Objects.equals(menuTree.getOrgType(),EnumConstant.ORG_TYPE_DEPART)){
                iterator.remove();
            }else if(Objects.equals(menuTree.getOrgType(),EnumConstant.ORG_TYPE_ROLE)){
                roles.add(menuTree);
                iterator.remove();
            }else if(Objects.equals(menuTree.getOrgType(),EnumConstant.ORG_TYPE_USER)){
                users.add(menuTree);
                iterator.remove();
            }
        }
        OrgTree role = new OrgTree();
        role.setOrgName("系统角色");
        role.setOrgType(EnumConstant.ORG_TYPE_ROLE);
        role.setOrgId(-10);
        role.setCanClick(false);

        role.setChilds(roles);
        dep.add(role);
        //未分配部门或角色的用户
        OrgTree nos = new OrgTree();
        nos.setOrgName("未分配角色的用户");
        nos.setOrgType(EnumConstant.ORG_TYPE_USER);
        nos.setOrgId(-11);
        role.setCanClick(false);
        nos.setChilds(users);
        dep.add(nos);
        return RS.data(dep);
    }

    @RequestMapping("/orgNameAuto")
    public Object orgNameAuto(@RequestParam(value = "q",required = false)String search, HttpServletResponse response){
        RS r = new RS();
        if(search!=null && !"".equals(search)){
            Map map=new HashMap();
            if(StringTool.isNotEmpty(search)){
                map.put("orgName","%"+search+"%");
                List<Map<String,Object>> list=orgService.getDepartmentTree(map);
                r.putData("list",list);
            }

        }
        return r;
    }
}

